/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package aso.upna.threads;

import aso.upna.cancion.AbstractCancion;
import aso.upna.config.ClientConfig;
import aso.upna.exceptions.MediaPlayerNotReady;
import aso.upna.exceptions.NoFileLoaded;
import aso.upna.exceptions.InvalidClassInstance;
import aso.upna.exceptions.PlaylistEmpty;
import aso.upna.net.ConnectionProtocol;
import aso.upna.net.ConnectionSettings;
import aso.upna.net.LookUpMessage;
import aso.upna.net.UserInfoMessage;
import aso.upna.playlist.PlayList;
import cliente.Reproductor;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;

/**
 *
 * @author triki
 */

public class PlayingThread extends Thread {

    private ClientConfig main_conf;
    private AbstractCancion cancion;
    private Reproductor rep;
    private PlayList playlist;
    private ConnectionProtocol conexion;
    private JProgressBar jpbar;
    private JLabel jlab;
    private JTextField jtext;
    private String user;
    private ClientConnect current_connect;
    private boolean thread_stop;
    private Thread peer_connect;
    
    public PlayingThread(Reproductor rep,ClientConfig conf,PlayList pl)
    {
        main_conf = conf;
        playlist = pl;
        this.rep = rep;
        thread_stop = false;
        jlab = null;
        jpbar = null;
        jtext = null;
        conexion = null;
        user = null;
    }

    public void registerConnection(ConnectionProtocol con)
    {
        conexion = con;
    }

    public void registerUser(String usr)
    {
        user = new String(usr);
    }

    public void unregisterUser()
    {
        if(user != null)
            user = null;
    }
    
    public void registerSwingObserver(JComponent comp) throws InvalidClassInstance
    {
        if(comp instanceof JProgressBar)
        {
            jpbar = (JProgressBar) comp;
            return;
        }
        
        if(comp instanceof JLabel)
        {
            jlab = (JLabel) comp;
            return;
        }

        if(comp instanceof JTextField)
        {
            jtext = (JTextField) comp;
            return;
        }
        
        throw new InvalidClassInstance();
    }

    @Override
    public void run()
    {
        String readFrom = null;
        AbstractCancion c_can = null;
        int count = 0;

        try
        {
            while(playlist.getCancionesRestantes() >= 0)
            {
                rep.setStopped(false);
                rep.setEnd(false);
                
                try
                {
                    //sacamos la cancion actual.
                    c_can = playlist.getActualCancion();
                    String title = c_can.getMetadatos().getTitulo();
                    String grupo = c_can.getMetadatos().getGrupo();

                    if(jtext != null)
                        jtext.setText(" "+grupo+" - "+title);
                    
                    //verificamos si es local o remota. Si es remota
                    //llamaremos a la funcion que desencadenara la conexion.
                } catch (PlaylistEmpty ex) {
                   return;
                }
                //verificamos si es local o remota. Si es remota
                //llamaremos a la funcion que desencadenara la conexion.

                //Si la cancion no es local, debemos desencadenar todo
                //el procedimiento de busqueda y reproduccion.

                if(jpbar != null)
                    jpbar.setValue(0);

                /* Procedimiento:
                 * 1. Como solo tenemos el UID, debemos obtener su IP y puerto.
                 * 2. Realizamos un user_lookup al servidor principal.
                 * 3. Este nos enviara un mensaje con la IP y puerto.
                 * 4. Si no existe, nos indicara que no existe el usuario.
                 * 5. Si obtenemos la IP y puerto, nos conectamos al otro usuario.
                 * 6. Pedimos la cancion y escuchamos en el puerto.
                 */

                if(!c_can.is_local())
                {
                    rep.setStopped(false);
                    thread_stop = false;
                    //System.out.println("Cancion remota");
                    if(!connect_and_buffering(c_can))
                    {
                        playlist.nextCancion();
                        continue;
                    }
                    //System.out.println("LOLLLLLLLL");
                }
                
                //sacamos la ruta desde la que leer la cancion.
                readFrom = readFrom(c_can);
                //cargamos la cancion en el reproductor.
                rep.setReady();
                rep.setFileName(readFrom);
                //Empezamos a reproducir.
                rep.play();
                
                while(!rep.hasEnd() && !thread_stop)
                {
                    try
                    {
                        if(count == 2){
                            System.out.println("pos: "+rep.getCurrentPosition());
                            count = 0;
                        }
                        Thread.sleep(500);
                        count++;
                    }
                    catch (InterruptedException ex)
                    {
                        return;
                    }
                }

                if(!c_can.is_local())
                {
                    current_connect.disconnect();
                }

                /*if(thread_stop)
                {
                    current_connect.disconnect();
                    peer_connect.interrupt();
                }*/
                
                if(rep.hasStopped())
                {
                    System.out.println("stoped");
                    if(!c_can.is_local())
                        current_connect.disconnect();
                    
                    return;
                }

                playlist.nextCancion();
                
            }
        }
        catch(MediaPlayerNotReady ex)
        {
            ex.printStackTrace();
        }
        catch (NoFileLoaded ex)
        {
            ex.printStackTrace();
        }
    }

    private String readFrom(AbstractCancion can)
    {
        if(can.is_local())
            return can.getRealPath();
        else
            return main_conf.getPathToTempFile();
    }

    private boolean connect_and_buffering(AbstractCancion can)
    {
        /* realizamos una peticion al servidor principal.
         * le pedimos que nos de, para un id de usuario x, su IP y puerto
         * necesarios para establecer la conexion P2P
         */
         if(conexion != null) //hay una conexion registrada.
         {
             if(conexion.is_connected())
             {
                UserInfoMessage msg = conexion.user_lookup(can.getPath(), can.getFilename());
                if(msg == null)//ha habido un fallo. El usuario no existia o no esta conectado.
                    return false;
                
                System.out.println("remote ip: "+msg.getIp());
                System.out.println("remote port: "+msg.getPort());

                if(user != null)
                    current_connect = new ClientConnect(main_conf,msg.getIp(),msg.getPort(),can.getFilename(),user);
                else
                    return false;
                
                current_connect.registerObserver(jpbar);
                peer_connect = new Thread(current_connect);
                peer_connect.start();

                while(jpbar.getValue() <= 15 && peer_connect.isAlive())
                {
                    try
                    {
                        if(rep.hasStopped())
                            break;
                        System.out.println("progreso: "+jpbar.getValue());
                        Thread.sleep(500);
                    }
                    catch (InterruptedException ex)
                    {
                       return false;
                    }
                }

                if(rep.hasStopped())
                {
                    current_connect.disconnect();
                    return false;
                }

                System.out.println("Buffered");
                if(jpbar.getValue() >= 15)
                    return true;
                
                return false;
             }
             return false;
         }
         return false;
    }
        /*
         * Una vez hayamos obtenido su IP y puerto, procedemos a estableces la conexion.
         */
        /*current_connect = new ClientConnect(main_conf, "127.0.0.1", 9999, "I_Can.mp3");
        current_connect.registerObserver(jpbar);
        Thread connect = new Thread(current_connect);
        connect.start();

        while(jpbar.getValue() <= 15 && connect.isAlive())
        {
            try
            {
                Thread.sleep(500);
            }
            catch (InterruptedException ex)
            {
                Logger.getLogger(PlayingThread.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        if(jpbar.getValue() >= 15)
            return true;
        return false;*/
  
    public void stopPeerThread()
    {
        //thread_stop = true;
        current_connect.disconnect();
    }
}
